/************************************************************************
Copyright (c) 2010, 2013, C.R. All rights reserved. 

E-mail: crtoyou@gmail.com; crtoyou@163.com

You can redistribute it and/or modify it under the terms of the
GNU Lesser General Public License as published by the
Free Software Foundation version 3 of the License.

This source code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. if not, write to the Free Software Foundation, Inc., 
51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
************************************************************************/

#ifndef __CR_SYNC_QUE_H__
#define __CR_SYNC_QUE_H__

#include <crdebug.h>
#include <crsync.h>
#include <list>

namespace cr {

template <class T>
class sync_que
{
public:
	sync_que(long size)
	{
		size_ = size;
		sph_get.initial(size, 0);
		sph_put.initial(size, size);
	}
	~sync_que()
	{
		lock.dolock();
		ASSERT(q_.empty());
		lock.unlock();
		sph_get.destroy();
		sph_put.destroy();
	}
	bool put(const T& data, int timeout = -1)
	{
		bool ret = false;
		if (sph_put.wait(timeout)){
			lock.dolock();
			ASSERT(q_.size() < size_);
			q_.push_front(data);
			lock.unlock();
			sph_get.release(1);
			ret = true;
		}
		return ret;
	}
	bool get(T& data, int timeout = 0)
	{
		bool ret = false;
		if (sph_get.wait(timeout)){
			lock.dolock();
			ASSERT(!q_.empty());
			data = q_.back();
			q_.pop_back();
			lock.unlock();
			sph_put.release(1);
			ret = true;
		}
		return ret;
	}

protected:
	std::list<T> q_;
	critical_section lock;
	semaphore sph_put, sph_get;
	size_t size_;
};

}//namespace

#endif //__CR_SYNC_QUE_H__